/**
 * 
 * purpose: scroll bar...
 * @auth: Ning
 * date: 2009-9-16
 * 
 * */
package com.components.scrollpane
{
	import com.components.button.MCButton;
	
	import core.section.Controller;
	
	import flash.display.DisplayObject;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Rectangle;
	import flash.media.Video;
	import flash.utils.Timer;

	public class ScrollBar extends Controller
	{
		//START...
		
		//PROPERTY...
		private var _position:Number;
		
		private var _maxPosition:Number;
		
		private var notAuto:Boolean;
		
		private var bar:MCButton;
		
		private var arrowUp:MCButton;
		
		private var arrowDown:MCButton;
		
		private var slide:MCButton;
		
		private var downStep:Number;
		
		private var wheelStep:Number;
		
		private var useWheel:Boolean;
		
		private var _autoAdd:Boolean;
		
		private var arrowTimer:Timer;
		
		private var step:Number;
		
		private const ARROW_TIMER_DELAY:uint = 100;
					
		private const MIN_BAR_HEIGHT:Number = 5;
		
		//CONSTRUCTOR...
		
		/**
		 * useWheel: could accept mouse wheel event or not
		 * autoAdd: bar will change height property when content height change
		 * downstep: the position changed when click arrow button
		 * wheelStep: the positon will be changed, when mouse wheel
		 * notAuto: the bar will always show or hide automatically.
		 * 
		 * */  
		
		public function ScrollBar(target:DisplayObject,useWheel:Boolean = false,autoAdd:Boolean = false,downStep:Number = 2,wheelStep:Number = 3,notAuto:Boolean = false)
		{
		
			this.notAuto = notAuto;	
			
			this.downStep = downStep;
			
			this.useWheel = useWheel;
			
			this.wheelStep = wheelStep;
			
			this.autoAdd = autoAdd;
			
			super(target);
			
			init();
		
		}
		
		//METHODS...
		
		//init...
		private function init():void
		{
			
			bar = new MCButton((target as Sprite).getChildByName("bar") as MovieClip);
						
			slide = new MCButton((target as Sprite).getChildByName("slide") as MovieClip);
			
			var arrowDownView:MovieClip = (target as Sprite).getChildByName("arrowDown") as MovieClip;
			
			if(arrowDownView)arrowDown = new MCButton(arrowDownView);
			
			var arrowUpView:MovieClip = (target as Sprite).getChildByName("arrowUp") as MovieClip;
			
			if(arrowUpView)arrowUp = new MCButton(arrowUpView);
			
			target.visible = false;
			
			if(arrowDown)
			{
				var spaceDown:Number = arrowDown.target.y - slide.target.y - slide.target.height;
			}
			
			var scaleX:Number = target.scaleX;
			
			var scaleY:Number = target.scaleY;
			
			target.scaleX = 1;
			
			target.scaleY = 1;
			
			slide.target.scaleX = scaleX;
			
			slide.target.scaleY = scaleY;
			
			if(arrowDown)arrowDown.target.y = slide.target.y + slide.target.height + spaceDown;
			
			position = 0;
			
			_maxPosition = 0;
			
			bar.target.y = slide.target.y;
						
			arrowTimer = new Timer(ARROW_TIMER_DELAY);
						
			configEventListeners();
				
		}
		
		//config element event listeners...
		private function configEventListeners():void
		{
			
			bar.target.addEventListener( MouseEvent.MOUSE_DOWN,barDownHandler);
			
			slide.target.addEventListener(MouseEvent.CLICK,slideClickHandler);
			
			if(useWheel) target.parent.addEventListener(MouseEvent.MOUSE_WHEEL,wheelHandler);
			
			if(arrowDown)arrowDown.addEventListener(MouseEvent.MOUSE_DOWN,arrowMouseDownHandler);
			
			if(arrowUp)arrowUp.addEventListener(MouseEvent.MOUSE_DOWN,arrowMouseDownHandler);
						
			arrowTimer.addEventListener(TimerEvent.TIMER,arrowTimerHandler);
			
		}
			
		
		//arrow timer handler...
		private function arrowTimerHandler(evt:TimerEvent):void
		{
			
			position += step;
			
		}
		
		//arrow  mouse down...
		private function arrowMouseDownHandler(evt:MouseEvent):void
		{
									
			var button:MCButton = evt.currentTarget as MCButton;
			
			button.target.stage.addEventListener(MouseEvent.MOUSE_UP,arrowMouseUpHandler);
						
			step = downStep * (button === arrowDown ? 1 : -1);
			
			arrowTimer.start();
			
		}
		
		//arrow mouase up...
		private function arrowMouseUpHandler(evt:MouseEvent):void
		{
			
			arrowTimer.stop();
			
			arrowTimer.reset();
			
		}
		
		
		//mouse wheel handler...
		private function wheelHandler(evt:MouseEvent):void
		{
			
			if(target.visible)
			{			
				position += wheelStep * (evt.delta > 0 ? -1 : 1)
			
			}
			
		}
		
		
		//slide click handler...
		private function slideClickHandler(evt:MouseEvent):void
		{
					
			position = target.mouseY - slide.target.y;
						
		}
		
		
		//on bar mouse down...
		private function barDownHandler(evt:MouseEvent):void
		{
			
			(bar.target as Sprite).startDrag(false,new Rectangle(bar.target.x,slide.target.y,0,maxPosition));
			
			bar.target.stage.addEventListener(MouseEvent.MOUSE_MOVE,stageMoveHandler);
			
			bar.target.stage.addEventListener(MouseEvent.MOUSE_UP,stageUpHandler);
			
			evt.stopPropagation();
							
		}
		
		//on mouse up on stage....
		private function stageUpHandler(evt:MouseEvent):void
		{
			
			bar.target.stage.removeEventListener(MouseEvent.MOUSE_MOVE,stageMoveHandler);
			
			bar.target.stage.removeEventListener(MouseEvent.MOUSE_UP,stageUpHandler);
			
			(bar.target as Sprite).stopDrag();
			
		}
		
		
		
		//on mouse move on stage...
		private function stageMoveHandler(evt:MouseEvent):void
		{
						
			position = bar.target.y - slide.target.y;
						
		}
		
		
		
		//update...
		public function update(showSize:Number,totalSize:Number):void
		{
								
			if(!notAuto)
			{
				
				target.visible = showSize < totalSize;
										
				
			}
				
			if(autoAdd)
			{
				
				var height:Number = showSize / totalSize * slide.target.height;
				
				height = height < MIN_BAR_HEIGHT ? MIN_BAR_HEIGHT : height;
				
				height = height > slide.target.height ? slide.target.height : height;
				
				bar.target.height = height;
				
			}
					
			_maxPosition = slide.target.height - bar.target.height;
									
			position = position > maxPosition ? maxPosition : position;
							
		}
				
		
		//set position...
		public function set position(val:Number):void
		{
						
			_position = val > maxPosition ? maxPosition : val;
			
			_position = _position < 0 ? 0 : _position;
									
			bar.target.y = slide.target.y + position;
									
			dispatchEvent(new ScrollPaneEvents(ScrollPaneEvents.POSITION_CHANGE,position / maxPosition));
			
		}
		
		//get position...
		public function get position():Number
		{
			
			return _position;
			
		}
		
		//get max position...
		public function get maxPosition():Number
		{
			
			return _maxPosition;
			
		}
		
		//set auto add...
		public function set autoAdd(val:Boolean):void
		{
		
			_autoAdd = val;
						
		}
		
		//get auto add...
		public function get autoAdd():Boolean
		{
			
			return _autoAdd;
			
		} 
		
		
		//END
	}
}